﻿using System;
using System.Diagnostics;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Emerald;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject
{
    /// <summary>
    /// Summary description for BenchmarkSorting
    /// </summary>
    [TestClass]
    public class BenchmarkSorting
    {
        static int amount = 7000;

        //static GameState[] expected = new[] { a7, a6, a5, a4, a3, a2, a1 }; // TODO: Initialize to an appropriate value

        public BenchmarkSorting()
        {
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestAll()
        {
            GameState[] m = GenerateGameStates(amount);
            GameState[] copy = new GameState[amount];

            Array.Copy(m, copy, amount);

            BenchmarkLinqSort(copy);

            Array.Copy(m, copy, amount);

            BenchmarkMergeSort(copy);

            Array.Copy(m, copy, amount);

            BenchmarkArraySort(copy);
        }

        [TestMethod]
        public void BenchmarkMergeSort(GameState[] m)
        {
            GameState[] actual;

            Stopwatch sw = Stopwatch.StartNew();

            actual = MoveOrdering.MergeSort(m, true);

            sw.Stop();

            Console.WriteLine("MergeSort:  " + sw.Elapsed);
        }

        [TestMethod]
        public void BenchmarkLinqSort(GameState[] m)
        {
            GameState[] actual;

            Stopwatch sw = Stopwatch.StartNew();

            // ascending
            actual = m.TakeWhile(gs => gs != null).OrderBy(gs => gs.EvalValue).ToArray();

            // descending
            //actual = m.TakeWhile(gs => gs != null).OrderByDescending(gs => gs.EvalValue).ToArray();

            sw.Stop();

            Console.WriteLine("Linq sort:  " + sw.Elapsed);
        }

        [TestMethod]
        public void BenchmarkArraySort(GameState[] m)
        {
            GameState[] actual;

            GameStateComparer gsc = new GameStateComparer(true);

            Stopwatch sw = Stopwatch.StartNew();

            Array.Sort(m, gsc);

            sw.Stop();

            Console.WriteLine("Array.Sort: " + sw.Elapsed);

        }

        public GameState[] GenerateGameStates(int amount)
        {
            GameState[] result = new GameState[amount];

            Random random = new Random();

            for (int i = 0; i < amount; i++)
            {
                result[i] = new GameState(EColor.White) { EvalValue = random.Next(amount) };
            }

            return result;
        }

        public class GameStateComparer : IComparer<GameState>
        {
            private bool ascending;

            public GameStateComparer(bool a)
            {
                ascending = a;
            }

            public int Compare(GameState x, GameState y)
            {
                return (x.EvalValue - y.EvalValue) * (ascending ? 1 : -1);
            }
        }

    }
}
